import store from '@/store'

export class QuestionValidate {
  question = null
  errors = []
  warnings = []
  constructor(question) {
    this.question = question
  }

  /**
   * 检查字符串中是否含有非下划线填空区
   * @param {*} str
   */
  hasInvalidBlank(str) {
    const blackList = ['（）', '()', '——', '--']
    return blackList.map(black => str.indexOf(black) >= 0).reduce((a, b) => a || b, false)
  }

  /**
   * 选择题答案是否合法
   * @param {*} answer
   * @param {*} options
   */
  isAnswerInOptions(answer, options) {
    if (answer.length !== 1) {
      return false
    } else {
      const code = answer.charCodeAt(0)
      return code >= 65 && code < (65 + options.length)
    }
  }

  /**
   * 检查题目类型是否合法
   */
  checkType() {
    const { type_id } = this.question
    const types = store.getters.types
    // 各种判断
    if (type_id === 0) {
      this.errors.push('必须选择一个题目类型')
    } else if (!types.find(it => it.id === type_id)) {
      this.errors.push('未找到题目类型')
    }
    return this
  }

  /**
   * 检查题目形式是否合法
   */
  checkStyle() {
    const { style } = this.question
    if (style !== 0 && style !== 1) {
      this.errors.push('题目形式要么是选择，要么是填空')
    }
    return this
  }

  /**
   * 检查题干是否合法
   */
  checkText() {
    const { text } = this.question
    if (text.length <= 0) {
      this.errors.push('题干不能为空')
    } else if (text.indexOf(' ') >= 0) {
      this.errors.push('题干不能包含空格')
    } else if (this.hasInvalidBlank(text)) {
      this.warnings.push('题干中好像包含错误的填空，题干空白处请统一使用4个英文半角下划线，例如：交通大学于____年西迁。')
    }
    return this
  }

  /**
   * 检查图片是否合法
   */
  checkImage(hasImage = false) {
    const { image } = this.question
    const clipMode = store.getters.questionCreateConfig.clip
    if (hasImage) {
      if (clipMode === 'manual' && image === null) {
        this.warnings.push('您选择了手动剪裁，但是还没有确定剪裁哦？')
      } else if (image === null) {
        this.errors.push('您选择了图片题，但是没有上传图片哦')
      }
    }
    return this
  }

  /**
   * 检查option_count
   */
  checkOptionCount() {
    const count = parseInt(this.question.option_count) || 4
    if (count < 2) {
      this.errors.push('选择题至少需要两个以上选项哦')
    }
    return this
  }

  /**
   * 检查选项是否合法
   */
  checkOptions() {
    const { style, options } = this.question
    if (style === 0) {
      if (options.length <= 0) {
        this.errors.push('选择题不能没有选项哦')
      }
      if (options.length === 1) {
        this.errors.push('选择题一个选项就不用选了……')
      }
      if (options.indexOf('') >= 0) {
        this.errors.push('选择题选项中不能存在空选项哦')
      }
      if (options.find(it => it.indexOf(' ') >= 0)) {
        this.errors.push('选项不能包含空格哦')
      }
      if (options.find(it => it.length > 50)) {
        this.errors.push('选项不能太长哦（不要超过50字）')
      }
      if (options.length !== (new Set(options)).size) {
        this.errors.push('选项不能有重复的哦')
      }
    }
    return this
  }

  /**
   * 检查答案是否合法
   */
  checkAnswer() {
    const { answer, style, options } = this.question
    if (answer.length <= 0) {
      this.errors.push('答案不能为空')
    } else if (style === 0 && !this.isAnswerInOptions(answer, options)) {
      this.errors.push('选择题答案必须从选项中选一个哦')
    }
    return this
  }

  /**
   * 获取检查结果
   */
  get() {
    return {
      errors: this.errors,
      warnings: this.warnings
    }
  }

  /**
   * 检查题目输入是否合法
   */
  isValid() {
    this.checkType()
    this.checkStyle()
    this.checkText()
    this.checkImage()
    this.checkOptions()
    this.checkAnswer()
    return this.get()
  }
}

/**
 * 检查题目输入是否合法
 */
export function isQuestionInputValid(question) {
  return new QuestionValidate(question).isValid()
}

/**
 * 静态检查类
 */
export const Question = {
  isValid(question) {
    return new QuestionValidate(question).isValid()
  },
  checkType(question) {
    return new QuestionValidate(question).checkType().get()
  },
  checkStyle(question) {
    return new QuestionValidate(question).checkStyle().get()
  },
  checkText(question) {
    return new QuestionValidate(question).checkText().get()
  },
  checkImage(question, hasImage = false) {
    return new QuestionValidate(question).checkImage(hasImage).get()
  },
  checkOptions(question) {
    return new QuestionValidate(question).checkOptions().get()
  },
  checkAnswer(question) {
    return new QuestionValidate(question).checkAnswer().get()
  }
}
